﻿package {
	import flash.display.AVM1Movie;
	import flash.display.Loader;
	import flash.display.MovieClip;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.net.URLRequest;
	import flash.events.Event;
	import flash.net.LocalConnection;
	import flash.events.MouseEvent;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;

	public class Cannon extends Sprite {
		
		//private var swf:MovieClip;
		// local connection instance to communicate to AVM1 movie
		var AVC_lc:LocalConnection = new LocalConnection();
		var exploded:Boolean;
		
		/** Constants values definition */
		public static const GRAVITY:Number = -9.81;	// Gravity value
		public static const TIME_FWD:Number = 0.07;   // Time forward precision TODO restore default
		public static const POWER_MAX:Number = 100;
		public static const POWER_MIN:Number = 10;
		public static const ANGLE_MAX:Number = 89;
		public static const ANGLE_MIN:Number = 0;
		public static const CANNON_HEIGHT:Number = 20;
		public static const CANNON_WIDTH:Number = 50;

		private var angle:Number;	// Angle of the cannon in  degrees
		private var power:Number;  // Determine the velocity of the ball
		private var player:Number;
		private var swf:MovieClip;
		private var scene:Scenary = Scenary.getInstance();

		public function Cannon(posX:Number,posY:Number,player:Boolean, angle:Number=60,power:Number=60) {
			this.x = posX;
			this.y = posY;
			this.angle = angle;
			this.power = power;
			this.player = 1;

			var req:URLRequest = new URLRequest("cannonfigure.swf");
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, init);
			loader.load(req);
			
			if (player) {
				this.scaleX = -1;
				this.x += CANNON_WIDTH;
				this.player = 2;
			}
			addEventListener(MouseEvent.CLICK, test);
		}
		private function test(e:MouseEvent) {
			
		}
		private function init(loadEvent:Event) {
			this.swf = loadEvent.currentTarget.content;
			addChild(swf);
			setAngle(this.angle); //UPDATE recamara angle
		}
		public function setAngle(angle:Number):void {
			this.angle = angle;
			this.rotation =  Math.pow(-1, this.player) * angle;//TODO: rotation only to the recamara
			//trace(this.swf.cannon_mc);
			//swf.cannon_mc.gotoAndPlay(OFFSET+angle);
		}

		public function getAngle():Number {
			return this.angle;
		}

		public function setPower(power:Number):void {
			this.power = power;
		}
		
		public function getPower():Number {
			return this.power;
		}

		/** Creation of the ball and init variables: time, position, velocity */
		private var ball:Ball;
		public function shootBall():Ball {
			swf.cannon_mc.play();
			var posX:Number = this.x + Math.pow(-1, this.player -1) * CANNON_WIDTH;
			var posY:Number = this.y;
			ball = new Ball(posX, posY);
			ball.vx = getVelocityX();
			ball.vy = getVelocityY();
			//trace(this.x + "||" + posX + "@@" + this.y + "||" + posY);

			// Listener which updates the ball position
			addEventListener(Event.ENTER_FRAME, nextPosition);

			return ball;
		}

		/** During the ball trayectory checks if there is any colision with other objects:
		- If impact with a tree crash it
		- If impact with the oponnent cannon WINS
		- If get out of the bounds: END of shoot */
		public function nextPosition(e:Event):void {
			var time:Number = ball.t;
//trace("VelocX:" + ball.vx + "|| PosX:" + ball.x + " # VelocY:" + ball.vy + "|| PosY:" + ball.y);
			ball.x = ball.x0 + ball.vx * time;
			ball.y =  ball.y0 + ball.vy * time - 1 / 2 * GRAVITY * Math.pow(time,2);
			time +=  TIME_FWD;

			ball.t = time;//TODO: ball.t is unusefull?
			//while(NOT_END) == no fin escenario | no impacto
			if(outOfBounds() || ballExplosion() || scenaryExplosion()) {
				scene.updateListeners();
				removeEventListener(Event.ENTER_FRAME, nextPosition);
				scene.removeChild(ball);
			}
			//TODO interaction with trees
			treeCollision();
		}
		private function ballExplosion():Boolean {
			var res:Boolean = false;
			var c1 = scene.objectList["cannon1"];
			var c2 = scene.objectList["cannon2"];
			
			if(player == 2 && ball.hitTestObject(c1)) {
				this.destroy(c1);
				res = true;
			}
			if(player == 1 && ball.hitTestObject(c2)) {
				this.destroy(c2);
				res = true;
			}
			
			if(res) {scene.btn_fire.enabled=false;/*TODO [DISABLE CONTROLS]*/}
			return res;
		}
		
		private function scenaryExplosion():Boolean {
			if(HitTest.complexHitTestObject(ball, scene.terrain)) {
			//if(ball.hitTestObject(scene.terrain)) {
				var i:int = 0;
				while(i < scene.objectList.explosions.length){
					var old_exp:Shape = scene.objectList.explosions[i];
					if(HitTest.complexHitTestObject(ball, old_exp)) {
						return false;
					}
					i++;
				}   
				var expl:Shape = new Shape();
				expl.graphics.beginFill(0xffffff);
				expl.graphics.drawCircle(ball.x,ball.y,ball.explosionRange);
				expl.graphics.endFill();
				scene.addChild(expl);
				// represent change in scenary
				scene.objectList.explosions.push(expl);
				
				if(Scenary.DEBUG)
					scene.drawXatPoint(ball.x, ball.y);
				return true;
			}
			return false;
		}
		
		private function treeCollision() { 
		//trace("TODO Cannon.treeCollision()");
			var trees = scene.objectList["trees"]; //tree list
			var ballAction:Ball = new Ball(ball.x, ball.y, 20);
			
			for (var key:String in trees) {
				if(ball.hitTestObject(trees[key])) {
					trees[key].crash();
				}
				else if(ballAction.hitTestObject(trees[key])) {
					trees[key].windMove();
				}
			}
		}
		
		private function destroy(c:Cannon) {
			trace("EXPLOSION CANNON "+ c.player +" Player "+ this.player +" WINS");
			// Play Cannon Explosion
			c.swf.cannon_mc.gotoAndPlay(30);
			//scene.removeChild(this);
			trace("END of Game");
		}
		
		private function outOfBounds():Boolean {
			if(ball.x > Scenary.WIDTH || ball.x < 0 || ball.y > Scenary.HEIGHT) {
				return true;
			}
			return false;
		}

		private function getVelocityX():Number {
			//Left (--->) or Right (<---) direction
			var direct:Number = Math.pow(-1, this.player - 1); 
			return direct * this.power * Math.cos(this.angle * Math.PI/180);
		}

		private function getVelocityY():Number {
			return -this.power * Math.sin(this.angle * Math.PI/180);
		}
	}
}